﻿using System.Collections.Generic;
using System.Linq;
using Framework.Core.BootStrapper.WindowsService;
using Framework.Core.Io;
using Framework.Core.Process;
using Rhino.Mocks;
using Xunit;

namespace Framework.Tests.Core.Process
{
    public class RemoteProcessControllerTest
    {
        class FakeCommand : ICommand
        {
            public string Name { get { return "Fake"; } }
            public string FileName { get { return "FakePath"; } }
            public string Arguments { get { return "FakArgs"; } }
            public bool IsNative { get { return true; } }
        }

        private readonly MockRepository mockRepository = new MockRepository();
        private readonly IProcessController remoteProcessController;
        private readonly IProcessController processControllerMock;

        public RemoteProcessControllerTest()
        {
            processControllerMock = mockRepository.StrictMock<IProcessController>();
            remoteProcessController = new RemoteProcessController(processControllerMock);
        }

        [Fact]
        public void Should_start_remote_process()
        {
            var fakeProcess = new FakeCommand();
            var result = new ProcessResult(0, string.Empty, string.Empty, false);
            processControllerMock.Expect(x => x.Start(fakeProcess, 10)).Return(result);
            mockRepository.ReplayAll();
            var processResult = remoteProcessController.Start(fakeProcess, 10);
            mockRepository.VerifyAll();

            Assert.Equal(result, processResult);
        }

        [Fact]
        public void Should_remote_kill_locker()
        {
            const string path = @"d:\toto";
            var process = GetProcess();
            processControllerMock.Expect(x => x.KillLocker(path))
                .Return(new List<IProcess>
                {
                    process
                });
            mockRepository.ReplayAll();
            var processStates = remoteProcessController.KillLocker(path);
            Assert.NotEmpty(processStates);
            Assert.Equal(process, processStates.First());
            mockRepository.VerifyAll();
        }

        private static Framework.Core.Process.Process GetProcess()
        {
            return new Framework.Core.Process.Process(0, "name", "fileName", "args", true);
        }

        [Fact]
        public void Should_kill()
        {
            var processState = GetProcess();
            processControllerMock.Expect(x => x.Kill(processState));
            mockRepository.ReplayAll();
            remoteProcessController.Kill(processState);
            mockRepository.VerifyAll();
        }

        [Fact]
        public void Should_install()
        {
            mockRepository.ReplayAll();
            var windowsServiceArgs = new WindowsServiceArgs();
            processControllerMock.Expect(x => x.Install(windowsServiceArgs));
            remoteProcessController.Install(windowsServiceArgs);
            mockRepository.VerifyAll();
        }

        [Fact]
        public void Should_uninstall()
        {
            mockRepository.ReplayAll();
            var windowsServiceArgs = new WindowsServiceArgs();
            processControllerMock.Expect(x => x.Uninstall(windowsServiceArgs));
            remoteProcessController.Uninstall(windowsServiceArgs);
            mockRepository.VerifyAll();
        }

        [Fact]
        public void Should_get_services()
        {
            mockRepository.ReplayAll();
            var services = new List<WindowsService>();
            processControllerMock.Expect(x => x.GetServices()).Return(services);

            Assert.Equal(services, remoteProcessController.GetServices());
            mockRepository.VerifyAll();
        }

        [Fact]
        public void Should_get_processes()
        {
            mockRepository.ReplayAll();
            var processes = new List<Framework.Core.Process.Process>();
            processControllerMock.Expect(x => x.GetProcesses()).Return(processes);

            Assert.Equal(processes, remoteProcessController.GetProcesses());
            mockRepository.VerifyAll();
        }

        [Fact]
        public void Should_construct_without_args()
        {
            Assert.NotNull(new RemoteProcessController("toto"));
        }
    }
}
